package ctrsystem

import (
	"cloud_worm/wormweb/controllers/ctrconfig"
	"cloud_worm/util/umodels/mysqldb"
	"cloud_worm/util/umodels/mysqldb/dbmanager"
	"github.com/astaxie/beego/logs"
	"fmt"
	"time"
	"strconv"
	"cloud_worm/wormweb/controllers/ctrsecurity/monitor"
	"cloud_worm/util/uhttp"
)

type ConfigController struct {
	ctrconfig.LoginCtr
}

func (c *ConfigController) List() {
	c.Manager()

	offset, limit := c.DealPage()
	status, err := c.GetInt("status", mysqldb.StatusAll)
	name := c.GetString("name")

	// cmd monitor和file monitor放在各自的配置页中处理，配置开关中不做展示
	// log collector放在各自的配置页面处理，不在配置开关中做显示
	noNameSet := []string{
		monitor.CmdMonitorEnableName,
		monitor.FileMonitorEnableName,
		monitor.LogCollectorEnableName,
	}

	conf := &dbmanager.WebConfig{}
	count, err := conf.Count(status, name, noNameSet)
	if err != nil {
		logs.Error(fmt.Sprintf("WebConfig count error: %s", err.Error()))
		data := map[string]interface{}{"total": 0, "data": []dbmanager.WebConfig{}}
		c.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "count error.", data)
		c.ServeJSON()
		return
	}
	type ConfigInfo struct {
		Id 			int64
		Name 		string
		Commit 		string
		Type 		string
		Value 		string
		Updated 	int64
		Status 		int				// 0: 有效；1：无效
	}
	if count == 0 {
		data := map[string]interface{}{"total": count, "data": []ConfigInfo{}}
		c.Data["json"] = uhttp.CreateOkResponse(data)
		c.ServeJSON()
		return
	}

	configs, err := conf.Select(offset, limit, status, name, noNameSet)
	if err != nil {
		logs.Error(fmt.Sprintf("WebConfig select error: %s", err.Error()))
		data := map[string]interface{}{"total": 0, "data": []dbmanager.WebConfig{}}
		c.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "select error.", data)
		c.ServeJSON()
		return
	}
	confs := make([]*ConfigInfo, 0, len(configs))
	for _, item := range configs {
		one := &ConfigInfo{
			Id: item.Id,
			Name: item.Name,
			Commit: item.Commit,
			Value: item.Value,
			Updated: item.Updated,
			Status: item.Status,
		}
		switch item.Type {
		case dbmanager.IntValue:
			one.Type = dbmanager.IntValueName
		case dbmanager.BoolValue:
			one.Type = dbmanager.BoolValueName
		case dbmanager.StringValue:
			one.Type = dbmanager.StringValueName
		}
		confs = append(confs, one)
	}

	data := map[string]interface{}{"total": count, "data": confs}
	c.Data["json"] = uhttp.CreateOkResponse(data)
	c.ServeJSON()
	return
}

func (c *ConfigController) Edit() {
	c.Manager()

	type InputInfo struct {
		Id 			int64			`json:"id"`
		Value 		string			`json:"value"`
	}
	var input InputInfo
	if err := c.Unmarshal(&input); err != nil {
		c.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeReqBodyErr, "config list edit input err.", nil)
		c.ServeJSON()
		return
	}

	conf := &dbmanager.WebConfig{Id: input.Id}
	if err := conf.Read("id"); err != nil {
		logs.Warn(fmt.Sprintf("WebConfig edit input id error: %s.", err.Error()))
		c.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input id error.", nil)
		c.ServeJSON()
		return
	}
	if c.checkValueValid(conf, input.Value) == false {
		// 参数检查
		logs.Error(fmt.Sprintf("WebConfig value type unkown"))
		c.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "WebConfig value type unkown", nil)
		c.ServeJSON()
		return
	}
	if err := ctrconfig.ExecConfigCheck(conf.Name, input.Value); err != nil {
		logs.Error(fmt.Sprintf("%s: %s", conf.Name, err.Error()))
		c.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, err.Error(), nil)
		c.ServeJSON()
		return
	}

	conf.Updated = time.Now().Unix()
	conf.Value = input.Value
	if err := conf.Update("updated", "name", "type", "value", "status"); err != nil {
		logs.Warn(fmt.Sprintf("WebConfig updated error: %s.", err.Error()))
		c.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "updated error.", nil)
		c.ServeJSON()
		return
	}

	if err := ctrconfig.ExecConfigLoad(conf.Name); err != nil {
		msg := fmt.Sprintf("加载 WebConfig (%s)错误: %s", conf.Name, err.Error())
		logs.Error(msg)
		// TODO： 通知说明
	}

	c.Data["json"] = uhttp.CreateOkResponse(nil)
	c.ServeJSON()
	return
}

func (c *ConfigController) checkValueValid(conf *dbmanager.WebConfig, value string) bool {
	switch conf.Type {
	case dbmanager.StringValue:
	case dbmanager.BoolValue:
		switch value {
		case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "Y", "y", "ON", "on", "On",
		"0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "N", "n", "OFF", "off", "Off":
			return true
		default:
			return false
		}
	case dbmanager.IntValue:
		if _, err := strconv.Atoi(value); err != nil {
			return false
		}

	default:
		return false
	}

	return true
}